package com.example.myhelloworld.client;
//import com.google.appengine.api.datastore.Key;
import java.util.Arrays;

import com.google.gwt.event.dom.client.KeyCodes;

import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class sudoku extends ExerciseClass{

	DockPanel dPanel;
	String userName;
	GreetingServiceAsync gsa;
	String mode;
	VerticalPanel sudokuGrid;
	HorizontalPanel[] rows;
	int[] cellContainArray = new int[81];

	public sudoku(String uName, String settings,
			GreetingServiceAsync GSA) {
		super(uName, settings, GSA);
		userName = uName;
		gsa = GSA;
		mode = settings;
		
		sudokuGrid = new VerticalPanel();
		sudokuGrid.addStyleName("sudoku");
		this.selfPanel = sudokuGrid;

		rows= new HorizontalPanel[9];
		sudokuHandler handler = new sudokuHandler(); 

		if (settings.length() == 81){
			for (int i = 0;i<81; i++){
				if (settings.charAt(i) == '.'){
					cellContainArray[i] = 0;
				} else {
					cellContainArray[i] = Integer.parseInt(String.valueOf(settings.charAt(i)));
				}
			}
		} else {
			System.out.println("INCORRECT NUMBER OF DIGITS: " + settings.length());
			for (int i = 0;i<81; i++){
				cellContainArray[i] = 0;
			}
		}
		int indexiterator = 0;
		
		for (int i = 0;i<9;i++){
			rows[i] = new HorizontalPanel();

			if (((i%3) == 0) && (i!=0)){
				HorizontalPanel cellDivider = new HorizontalPanel();
				cellDivider.setSpacing(3);
				cellDivider.add(new Label());//nonsense empty label, activates spacing, so that we get something that looks like an empty row
				sudokuGrid.add(cellDivider);
			}
			
			for (int j = 0;j<9;j++){
				indexiterator++;
				if (((j%3) == 0) && (j!=0)){
					Label rowDivider = new Label();
					rowDivider.setWidth("6px");
					rows[i].add(rowDivider);
				}
				
				VerticalPanel cell = new VerticalPanel();
				cell.setSize("40px", "40px");
				cell.addStyleName("sudokuCell");
				
				TextBox subCell = new TextBox();
				if (cellContainArray[indexiterator-1] != 0){
					subCell.setText(cellContainArray[indexiterator-1]+"");
				} else {
					subCell.setText("");
				}
				subCell.setSize("40px", "40px");
				subCell.addKeyDownHandler(handler);
				
				subCell.addStyleName("subSudokuCell");
				cell.add(subCell);
				rows[i].add(cell);
				
			}
			sudokuGrid.add(rows[i]);
		}
		System.out.println("Added all cells!");
		int[] test = {9,2,7,5,3,6,1,8,4};
		System.out.println("Findingtest: " + oneToNinePresent(test));
		produceResultButton = new Button("Proceed");
		sudokuGrid.add(produceResultButton);
		selfPanel = sudokuGrid;
	}
	
	public boolean sudokuCorrect(int[] cellArray) {
		System.out.println("Current sudoku-state: \n");
		for (int i = 0;i<81;i++){
			System.out.print(cellArray[i]);
			if (i%9 == 8){
				System.out.println();
			}
		}
		System.out.println();
		
		for (int i = 0; i<9;i++){	//takes each row, one at a time, and checks if all numbers are within it.
			int[] correctRow = new int[9];
			int[] correctCol = new int[9];
			int[] correctBox = new int[9];
			
			//Correct all rows:
			for (int j = 0;j<9;j++){
				correctRow[j] = cellArray[i*9+j];
			}
			
			//correct all columns:
			for (int j = 0;j<9;j++){
				correctCol[j] = cellArray[j*9+i];	
			}
			
			for (int j = 0;j<9;j++){
				
				
				int row = (i / 3) * 3 + j/3;
				int col = j%3 + (i%3)*3;
				correctBox[j] = cellArray[row*9+col];	
				
				
				//i==2 i/3=0      row =  (i/3)*3=000000000 + j/3 = 000111222 = 000111222
				//j=1:9 			col:  j%3 = 012012012 + (i%3)*3 = 666666666 = 789789789
				if (i==2){
					System.out.println("Boxelements" + cellArray[row*9+col]  + "  -  Row: " + row + " Col: " + col  );
				}
				//  rad:(i/3  000111222 + j%3 012012012) , kolumn: j%3 012012012 + i/3)         
			}
			
			if (!(oneToNinePresent(correctRow) && oneToNinePresent(correctRow) &&oneToNinePresent(correctRow))){
				return false;
			}
			
			System.out.println(oneToNinePresent(correctBox));
		}
		return true;
	}
	private boolean oneToNinePresent(int[] rowOrCell){
//		System.out.println("###########################################");
		for (int i = 0; i<9;i++){
//			System.out.println("TestList, row:" + (i+1));
			int iPresent = 0;
			for (int j = 0; j<9;j++){
				if (i+1==rowOrCell[j]){
					iPresent++;
//					System.out.print(rowOrCell[j] + " ");
				}
			}
			if (iPresent != 1){
//				System.out.println("Number: " + (i+1) + " Occurences: " + iPresent);
				return false;
			}
		}
		return true;
	}
	

	@Override
	public void draw() {
	}

	@Override
	public String pushresult() {
		boolean result = sudokuCorrect(cellContainArray);
		int points = 0;
		if (result) {
			points = 100;
		}
		
		return Integer.toString(points);
	}
	/**
	 * 
	 * @author Habbe
	 * sudokuHandler takes care of key-events, when the arror-buttons are pressed, the cursor moves around, and when the 1-9 digits are pressed, they are printed in one box.
	 */
	class sudokuHandler implements KeyDownHandler{

		public void onKeyDown(KeyDownEvent event) {
			// TODO Auto-generated method stub
			int coordRow = findActiveRow(event);
			int coordCol = findActiveColumn(event,coordRow);
			if (event.getNativeKeyCode() == KeyCodes.KEY_UP) {
				System.out.println("Key Up!!!! : " + coordRow + " : " + coordCol);
				int spacingRemove = 0; 
				if (((coordRow-1)%3) == 0){
					spacingRemove = 1;
				}
				System.out.println("Space: " + spacingRemove);
				VerticalPanel verticalCell = (VerticalPanel) rows[(coordRow-1+rows.length)%rows.length].getWidget(coordCol);

				TextBox inside = (TextBox) verticalCell.getWidget(0);
				inside.setFocus(true);
			}
			if (event.getNativeKeyCode() == KeyCodes.KEY_DOWN) {
				System.out.println("Key Down!!!! : " + coordRow + " : " + coordCol);
				VerticalPanel verticalCell = (VerticalPanel) rows[(coordRow+1)%rows.length].getWidget(coordCol);
				TextBox inside = (TextBox) verticalCell.getWidget(0);
				inside.setFocus(true);
			}
			if (event.getNativeKeyCode() == KeyCodes.KEY_LEFT) {
				System.out.println("Key Left!!!! : " + coordRow + " : " + coordCol);
				int spacingRemove = 0; 
				if ((coordCol == 4) || ( coordCol == 8)){
					spacingRemove = 1;
				}
//				System.out.println("Space: " + spacingRemove);
				VerticalPanel verticalCell = (VerticalPanel) rows[(coordRow)%rows.length].getWidget((coordCol-1-spacingRemove+rows[coordRow].getWidgetCount())%rows[coordRow].getWidgetCount());
				TextBox inside = (TextBox) verticalCell.getWidget(0);
				inside.setFocus(true);
			}

			if (event.getNativeKeyCode() == KeyCodes.KEY_RIGHT) {
				System.out.println("Key Right!!!! : " + coordRow + " : " + coordCol);
				int spacingRemove = 0; 
				if ((coordCol == 2) || ( coordCol == 6)){
					spacingRemove = 1;
				}
//				System.out.println("Space: " + spacingRemove);
				VerticalPanel verticalCell = (VerticalPanel) rows[(coordRow)%rows.length].getWidget((coordCol+1+spacingRemove)%rows[coordRow].getWidgetCount());
				TextBox inside = (TextBox) verticalCell.getWidget(0);
				inside.setFocus(true);
			}
			
			if ((event.getNativeKeyCode() > 48) && (event.getNativeKeyCode() < 58)) {
//				System.out.println("Key Right!!!! : " + coordRow + " : " + coordCol);
				int spacingRemove = 0; 
				if ((coordCol == 2) || ( coordCol == 6)){
					spacingRemove = 1;
				}
				VerticalPanel verticalCell = (VerticalPanel) rows[coordRow].getWidget(coordCol);
				TextBox inside = (TextBox) verticalCell.getWidget(0);
//				inside.setText(""+(event.getNativeKeyCode()-48));
				inside.setText("");	//somehow the adding text with key seems to occur after this has been handled
				int adjustCol = 0;		//adjustCol to adjust coordinates for the occurences of the empty columns/spacings between block 3-4 and 6-7
				if ((coordCol >=3)&&(coordCol <=6)){
					adjustCol = 1;//*(coordRow+1);
				}
				if (coordCol >6){
					adjustCol = 2;//*(coordRow+1);
				}
				
				System.out.println("AdjustNumber"+ adjustCol + " Coordrow: " + coordRow + " CoordCol: " +coordCol);
				cellContainArray[9*coordRow+coordCol-adjustCol] = (event.getNativeKeyCode()-48);
				System.out.println("Added to sudoku array: " + (event.getNativeKeyCode()-48));
				System.out.println("Added to array: " + (9*coordRow+coordCol-adjustCol) + " Row: " + coordRow + " Col: "  + (coordCol-adjustCol));
				boolean sudokuCompleted = sudokuCorrect(cellContainArray);
				if (sudokuCompleted){
					System.out.println("Sudoku completed!");
					sudokuGrid.removeFromParent();
				}
				
			}else{
	
			}
		}
		
		// Not nice, but a way without creating and using a Point-object.
		int findActiveRow(KeyDownEvent event){
//			System.out.println("Finding rows?");
			for (int i = 0;i<rows.length;i++){
				for (int j = 0; j < rows[i].getWidgetCount(); j++){
					try {
						if (((VerticalPanel)(rows[i].getWidget(j))).getWidget(0) == event.getSource()){
							return i;
						}
					} catch (Exception e) {}
				} 
			}
			return 0;
		}
		int findActiveColumn(KeyDownEvent event, int row){
//			System.out.println("Finding cols?");
			for (int j = 0; j < rows[row].getWidgetCount(); j++){
				try {
					if (((VerticalPanel)(rows[row].getWidget(j))).getWidget(0) == event.getSource()){
						return j;
					}
				} catch (Exception e) {}
			} 
			return 0;
		}	
	}
}
